package com.pkk.cloud.support.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pkk.cloud.support.admin.bo.RoleClientCateAndMenuResourceSimpeBo;
import com.pkk.cloud.support.admin.bo.RoleClientResourceSimpeBo;
import com.pkk.cloud.support.admin.dto.req.resources.OauthResourceIdReqDto;
import com.pkk.cloud.support.admin.dto.req.resources.OauthResourcePidReqDto;
import com.pkk.cloud.support.admin.dto.req.resources.OauthResourceRoleBindReqData;
import com.pkk.cloud.support.admin.dto.req.resources.OauthResourceUpdateIdReqDto;
import com.pkk.cloud.support.admin.dto.req.resources.OauthServerClientAllResourceSimpleReqDto;
import com.pkk.cloud.support.admin.dto.resp.resources.OauthResourceSimpleRespDto;
import com.pkk.cloud.support.admin.dto.resp.server.OauthServerClientSimpleRespDto;
import com.pkk.cloud.support.admin.entity.resource.PenguinSysResource;
import com.pkk.cloud.support.admin.entity.resource.PenguinSysRoleResource;
import com.pkk.cloud.support.admin.mybatis.resource.PenguinSysResourceMapper;
import com.pkk.cloud.support.admin.service.PenguinSysResourceService;
import com.pkk.cloud.support.admin.service.PenguinSysRoleResourceService;
import com.pkk.cloud.support.admin.service.PenguinSysServerService;
import com.pkk.cloud.support.common.admin.constand.ResourceConstandEnum.ResourceTypeEnum;
import com.pkk.cloud.support.common.admin.dto.req.resource.SysResourceMenuReqDto;
import com.pkk.cloud.support.common.admin.dto.resp.resource.ServerMenuRespDto;
import com.pkk.cloud.support.common.admin.dto.resp.resource.SysResourceMenuRespDto;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

@Slf4j
@Service
public class PenguinSysResourceServiceImpl extends ServiceImpl<PenguinSysResourceMapper, PenguinSysResource> implements
    PenguinSysResourceService {


  @Resource
  private PenguinSysServerService penguinSysServerService;
  @Resource
  private PenguinSysRoleResourceService penguinSysRoleResourceService;


  /**
   * @Description: 获取处理之后的菜单信息
   * @Param: body
   * @return: java.util.List<com.pkk.cloud.support.admin.common.dto.resp.resource.SysResourceMenuRespDto>
   * @Author: peikunkun
   * @Date: 2020/3/16 0016 下午 5:51
   */
  @Override
  public ServerMenuRespDto getClientMenusByServerId(SysResourceMenuReqDto body, Long userId) {
    List<PenguinSysResource> resources = this.findSysResourceByServerName(body.getServerName(), userId);
    List<String> buttons = this.findSysResourceButtonByServerName(body.getServerName(), userId);
    return ServerMenuRespDto.builder().resources(convertSysResourceMenu(resources)).buttons(buttons).build();
  }

  /**
   * @Description: 转换一级二级资源到特定的类
   * @Param: resources
   * @return: java.util.List<com.pkk.cloud.support.common.admin.dto.resp.resource.SysResourceMenuRespDto>
   * @Author: peikunkun
   * @Date: 2020/3/26 0026 下午 1:52
   */
  private List<SysResourceMenuRespDto> convertSysResourceMenu(List<PenguinSysResource> resources) {
    // 菜单集合
    List<SysResourceMenuRespDto> userMenuVos = new ArrayList<SysResourceMenuRespDto>();
    if (CollectionUtils.isEmpty(resources)) {
      return userMenuVos;
    }

    for (PenguinSysResource categoryResource : resources) {
      //一级菜单
      if (ResourceTypeEnum.CATEGORY.getValue().equals(categoryResource.getResourceType())) {
        SysResourceMenuRespDto category = convertResourceDto(categoryResource);

        //二级的操作
        List<SysResourceMenuRespDto> childrenList = new ArrayList();
        for (PenguinSysResource menuResource : resources) {
          if (menuResource.getResourcePid().equals(categoryResource.getId())) {
            childrenList.add(convertResourceDto(menuResource));
            continue;
          }
        }
        category.setChildResource(childrenList);
        //增加一级菜单
        userMenuVos.add(category);
      }
    }
    return userMenuVos;
  }

  /**
   * @Description: 将查询的实体转换为菜单dto
   * @Param: categoryResource
   * @return: com.pkk.cloud.support.common.admin.dto.resp.resource.SysResourceMenuRespDto
   * @Author: peikunkun
   * @Date: 2020/3/26 0026 下午 2:21
   */
  private SysResourceMenuRespDto convertResourceDto(PenguinSysResource resources) {
    return SysResourceMenuRespDto.builder().classIcon(resources.getClassIcon()).id(resources.getId())
        .resourceCode(resources.getResourceCode()).resourceLevel(resources.getResourceLevel())
        .resourceName(resources.getResourceName()).resourceSort(resources.getResourceSort())
        .resourceUrl(resources.getResourceUrl()).build();
  }

  /**
   * @Description: 依据服务名称获取资源信息
   * @Param: serverName:服务名称req resp
   * @return: java.util.List<com.pkk.cloud.support.admin.entity.resource.PenguinSysResource>
   * @Author: peikunkun
   * @Date: 2020/3/16 0016 下午 5:53
   */
  @Override
  public List<PenguinSysResource> findSysResourceByServerName(String serverName, Long userId) {
    final HashMap<String, Object> param = new HashMap<>(3);
    param.put("serverName", serverName);
    param.put("userId", userId);
    return baseMapper.findSysResourceByServerName(param);
  }

  /**
   * @Description: 根据服务查询按钮资源
   * @Param: serverId
   * @Param userId
   * @return: java.util.List<java.lang.String>
   * @Author: peikunkun
   * @Date: 2020/3/26 0026 下午 2:24
   */
  @Override
  public List<String> findSysResourceButtonByServerName(String serverName, Long userId) {
    final HashMap<String, Object> param = new HashMap<>(3);
    param.put("serverName", serverName);
    param.put("userId", userId);
    return baseMapper.findSysResourceButtonByServerName(param);
  }


  /**
   * @Description: 依据客户端id查询客户端资源信息
   * @Param: clientId
   * @return: java.util.List<com.pkk.cloud.support.admin.bo.RoleClientResourceSimpeBo>
   * @Author: peikunkun
   * @Date: 2020/4/10 0010 上午 11:18
   */
  @Override
  public List<RoleClientResourceSimpeBo> findClientAllResourceByClientId(String clientId) {
    return baseMapper.findClientAllResourceByClientId(clientId);
  }


  /**
   * @Description: 依据客户端id查询客户端资源信息[获取菜单与分类]
   * @Param: clientId
   * @return: java.util.List<com.pkk.cloud.support.admin.bo.RoleClientResourceSimpeBo>
   * @Author: peikunkun
   * @Date: 2020/4/10 0010 上午 11:18
   */
  @Override
  public List<RoleClientCateAndMenuResourceSimpeBo> findClientCateAndMenuResourceByClientId(String clientId) {
    return baseMapper.findClientCateAndMenuResourceByClientId(clientId);
  }

  /**
   * @Description: 获取角色id查询角色资源id
   * @Param: roleId
   * @return: java.util.List<java.lang.Long>
   * @Author: peikunkun
   * @Date: 2020/4/10 0010 上午 11:40
   */
  @Override
  public Set<Long> findRoleResourceIdByRoleId(Long roleId) {
    return baseMapper.findRoleResourceIdByRoleId(roleId);
  }

  /**
   * @Description: 绑定资源与角色的关系
   * @Param: body
   * @return: boolean
   * @Author: peikunkun
   * @Date: 2020/4/11 0011 下午 12:41
   */
  @Override
  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
  public boolean bindResourceRole(OauthResourceRoleBindReqData body) {
    //获取属于该客户端资源
    Set<Long> resourceIdByOwnClientId = baseMapper.findSysResourceIdsByOwnClientId(body.getClientId());
    final Long roleId = body.getRoleId();

    //删除该客户单与指定角色的资源绑定关系
    if (!CollectionUtils.isEmpty(resourceIdByOwnClientId)) {
      resourceIdByOwnClientId.stream().forEach(r -> {
        UpdateWrapper<PenguinSysRoleResource> condition = new UpdateWrapper<>();
        condition.eq("role_id", roleId);
        condition.eq("resource_id", r);
        penguinSysRoleResourceService.remove(condition);
      });
    }

    //重新绑定该客户端的资源与角色的绑定关系
    if (!CollectionUtils.isEmpty(body.getResourceIds())) {
      final ArrayList<PenguinSysRoleResource> penguinSysRoleResources = new ArrayList<>();
      body.getResourceIds().forEach(r -> {
        penguinSysRoleResources.add(PenguinSysRoleResource.builder().resourceId(r).roleId(roleId).build());
      });
      penguinSysRoleResourceService.saveBatch(penguinSysRoleResources);
    }
    return true;
  }


  /**
   * @Description: 获取所有菜单-包括服务/资源/按钮
   * @Param: body
   * @return: java.util.List<com.pkk.cloud.support.admin.dto.resp.server.OauthServerClientAllResourceSimpleRespDto>
   * @Author: peikunkun
   * @Date: 2020/4/11 0011 下午 1:27
   */
  @Override
  public List<OauthServerClientSimpleRespDto> getServerClientAllResource(
      OauthServerClientAllResourceSimpleReqDto body) {
    //服务组与子级客户端
    final List<OauthServerClientSimpleRespDto> serverClient = penguinSysServerService.getServerClient();
    serverClient.stream().forEach(server -> {
      server.getChildren().stream().forEach(client -> {
        final String clientId = client.getKey();
        client.setChildren(penguinSysServerService.getClientResource(clientId));
      });
    });
    return serverClient;
  }


  /**
   * @Description: 获取资源信息依据父id
   * @Param: request
   * @Author: peikunkun
   * @Date: 2020/4/11 0011 下午 7:41
   */
  @Override
  public List<OauthResourceSimpleRespDto> getResourceByPid(OauthResourcePidReqDto body) {
    return baseMapper.getResourceByPid(body);
  }

  /**
   * @Description: 添加资源信息
   * @Param: penguinSysResource
   * @Param userId
   * @return: boolean
   * @Author: peikunkun
   * @Date: 2020/4/18 0018 下午 3:13
   */
  @Override
  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
  public boolean addResource(List<PenguinSysResource> penguinSysResource, String userId) {
    penguinSysResource.stream().forEach(a -> {
      baseMapper.insert(a);
    });
    return true;
  }


  /**
   * @Description: 获取资源信息
   * @Param: body
   * @return: com.pkk.cloud.support.admin.dto.resp.resources.OauthResourceSimpleRespDto
   * @Author: peikunkun
   * @Date: 2020/4/18 0018 下午 3:45
   */
  @Override
  public OauthResourceSimpleRespDto getResourceById(Long resourceId) {
    return baseMapper.getResourceById(resourceId);
  }

  /**
   * @Description: 删除资源信息
   * @Param: request
   * @return: com.pkk.components.rpc.response.CommonResponse<java.lang.Boolean>
   * @Author: peikunkun
   * @Date: 2020/4/21 0021 下午 3:31
   */
  @Override
  public Boolean delResourceById(OauthResourceIdReqDto body, String userId) {
    PenguinSysResource penguinSysResource = new PenguinSysResource();
    penguinSysResource.setId(body.getResourceId());
    penguinSysResource.setIsDeleted(true);
    penguinSysResource.setUpdateName(userId);
    penguinSysResource.setUpdateTime(new Date());
    return baseMapper.updateById(penguinSysResource) == 1;
  }


  /**
   * @Description: 更新资源依据id
   * @Param: request
   * @return: com.pkk.components.rpc.response.CommonResponse<java.lang.Boolean>
   * @Author: peikunkun
   * @Date: 2020/4/21 0021 下午 4:05
   */
  @Override
  public Boolean updateResourceById(OauthResourceUpdateIdReqDto body, String userId) {
    PenguinSysResource penguinSysResource = new PenguinSysResource();
    BeanUtils.copyProperties(body, penguinSysResource);
    penguinSysResource.setUpdateName(userId);
    penguinSysResource.setUpdateTime(new Date());
    return baseMapper.updateById(penguinSysResource) == 1;
  }
}
